package com.zhuss.product.processor;

import java.util.*;
import java.util.stream.Collectors;

import com.zhuss.bean.unit.linesite.BoardBean;
import com.zhuss.bean.unit.linesite.DateBean;
import com.zhuss.bean.vo.product.line.DetailLineVo;
import com.zhuss.bean.vo.product.line.ListLineSiteVo;
import com.zhuss.enums.*;
import com.zhuss.exception.ExceptionCode;
import com.zhuss.product.db.dao.ext.*;
import com.zhuss.product.db.entity.Train;
import com.zhuss.product.processor.cache.*;
import com.zhuss.util.DateUtil;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import com.zhuss.bean.bo.product.train.CreateLineStrategyBo;
import com.zhuss.common.AbstractProcessor;
import com.zhuss.common.Processor;
import com.zhuss.product.db.entity.LineStrategy;
import com.zhuss.db.entity.OpLog;
import com.zhuss.exception.DzcxException;
import com.zhuss.util.JsonUtil;

import org.springframework.transaction.annotation.Transactional;

import static java.util.stream.Collectors.toList;


/**
 * @description: 线路策略创建
 * @author: zhushanshuo
 * @create: Mon Jan 04 09:51:07 CST 2021
 **/
@Component("lineStrategyCreate")
public class LineStrategyCreate extends AbstractProcessor<Object, CreateLineStrategyBo> implements Processor<Object, CreateLineStrategyBo> {

    @Autowired
    private LineStrategyDao lineStrategyDao;

    @Autowired
    private LineStrategySiteDao lineStrategySiteDao;

    @Autowired
    private LineSiteDao lineSiteDao;

    @Autowired
    private TrainDao trainDao;

    @Autowired
    @Qualifier("lineCache")
    private LineCache lineCache;

    @Autowired
    @Qualifier("lineStrategyCache")
    private LineStrategyCache lineStrategyCache;

    @Autowired
    @Qualifier("trainCache")
    private TrainCache trainCache;

    @Autowired
    @Qualifier("siteCache")
    private SiteCache siteCache;

    @Autowired
    @Qualifier("siteStrategyCache")
    private SiteStrategyCache siteStrategyCache;

    /**
     * 校验
     */
    @Override
    public void check(CreateLineStrategyBo param) throws DzcxException {

        if (param.getLineId() == null || param.getLineId() <= 0l) {
            throw new DzcxException(ExceptionCode.线路ID为空);
        }
        if (param.getCanSell() == null || param.getCanSell() <= 0l) {
            throw new DzcxException(ExceptionCode.是否售卖为空);
        }
        List<ListLineSiteVo> siteVos = lineSiteDao.listByLineId(param.getLineId());
        if (siteVos.size() == 0) {
            throw new DzcxException(ExceptionCode.该线路下没有绑定站点);
        }
        param.setSiteVos(siteVos);

        if (param.getBoardList().size() == 0) {
            throw new DzcxException(ExceptionCode.请选择要发布的班次);
        }

        if (param.getStartDate() == null) {
            throw new DzcxException(ExceptionCode.运营开始日期不能为空);
        }
        if (param.getEndDate() == null) {
            throw new DzcxException(ExceptionCode.运营结束日期不能为空);
        }
        List<Date> finalResDateList = dateHandler(param.getStartDate(),param.getEndDate(),param.getStrategyType());
        if (finalResDateList.size() == 0 || finalResDateList == null) {
            throw new DzcxException(ExceptionCode.该班次类别下没有运营日期);
        }
        param.setFinalResDateList(finalResDateList);
    }

    /**
     * 操作方法
     */
    @Override
    @Transactional
    public Object process(CreateLineStrategyBo param) throws DzcxException {
        //根据boardList决定t_line_strategy表中的数据
        DetailLineVo lineVo = lineCache.get(param.getLineId());

        List<Date> finalResDateList = param.getFinalResDateList();
        finalResDateList = finalResDateList.stream().sorted().collect(Collectors.toList());
        List<ListLineSiteVo> siteVos = param.getSiteVos();
        Long price = siteVos.get(siteVos.size() - 1).getPrice();
        for (BoardBean boardBean : param.getBoardList()) {
            LineStrategy lineStrategy = new LineStrategy();
            BeanUtils.copyProperties(param,lineStrategy);
            lineStrategy.setBoardNo(boardBean.getNo());
            lineStrategy.setStartTime(boardBean.getTime());
            lineStrategy.setLineType(lineVo.getType());
            lineStrategy.setLineName(lineVo.getName());
            if (!param.getStrategyType().equals(StrategyType.everyday.key())) {
                lineStrategy.setEndDate(finalResDateList == null ? null : DateUtil.someMinuteLater(finalResDateList.get(finalResDateList.size() - 1),
                        boardBean.getTime(),lineVo.getIntervals()));
            }
            lineStrategy.setIntervals(lineVo.getIntervals());
            lineStrategy.setDeleted(0);
            lineStrategy.setCreator(param.getConcurrentUserName());
            lineStrategy.setCreatorId(param.getConcurrentUserId());
            lineStrategy.setCreateTime(new Date());
            lineStrategyDao.create(lineStrategy);
            //清除根据线路类型查询的策略
            if (lineStrategy.getStatus().equals(OperationStatus.已开通.key())) {
                siteStrategyCache.clealAll();
            }
            //根据line_id,line_strategy_id决定t_line_strategy_site表中数据
            lineStrategySiteDao.batchInsert(lineVo.getName(),siteVos,lineStrategy.getLineStrategyId());
            siteCache.clear();
            lineStrategy.setPrice(price);
            lineStrategyDao.updateByPrimaryKey(lineStrategy);
            lineStrategyCache.clear(lineStrategy.getLineStrategyId());
            //根据 startDate、endDate、strategyType决定t_train表中信息
            saveTrain(finalResDateList,lineVo,boardBean,param,lineStrategy,price);
        }
        return null;
    }

    public void saveTrain(List<Date> finalResDateList,DetailLineVo lineVo,BoardBean boardBean,
                          CreateLineStrategyBo bo,LineStrategy lineStrategy,Long price) {
        List<Train> trains = new ArrayList<>();
        for (Date date : finalResDateList) {
            Train train = new Train();
            BeanUtils.copyProperties(lineVo,train);
            train.setLineName(lineVo.getName());
            train.setPrice(price);
            train.setLineStrategyId(lineStrategy.getLineStrategyId());
            train.setDate(date);
            train.setCanSell(bo.getCanSell());
            train.setLineType(lineVo.getType());
            train.setStartTime(DateUtil.someMinuteLater(date,boardBean.getTime(),0));
            train.setEndTime(DateUtil.someMinuteLater(date,boardBean.getTime(),lineStrategy.getIntervals()));
            train.setTotal(lineVo.getPeopleQuantity() != null ? Long.valueOf(lineVo.getPeopleQuantity()) : null);
            train.setStatus(bo.getStatus());
            train.setCreatorId(bo.getConcurrentUserId());
            train.setCreator(bo.getConcurrentUserName());
            train.setCreateTime(new Date());
            trains.add(train);
        }
        trainDao.insert(trains);
        trainCache.clear(0l);
    }

    /**
     * 从listA里删除listB里有的数据
     *
     * @param listA
     * @param listB
     * @return
     */
    public static List<Date> listrem(List<Date> listA,List<Date> listB) {
        for (Iterator<Date> itA = listA.iterator(); itA.hasNext(); ) {
            Date temp = itA.next();
            // itA.next() 只能在外层循环里面调用1次
            for (int i = 0; i < listB.size(); i++) {
                if (temp.equals(listB.get(i))) {
                    itA.remove();
                }
            }
        }
        return listA;
    }

    public List<Date> dateHandler(Date startDate,Date endDate,Integer strategyType) throws DzcxException {
        //查询节假日表
        List<Date> resDateList = new ArrayList<>();
        List<DateBean> holidayList = lineStrategyDao.holiday();
        //如果endDate大于今年的最后一天，而且大于表中的最大的数据，给提示
        if (strategyType.equals(StrategyType.workday.key()) ||
                strategyType.equals(StrategyType.holiday.key())) {
            if (endDate.after(DateUtil.getCurrYearLast()) &&
                    endDate.after(holidayList.get(0).getDate())) {
                throw new DzcxException(ExceptionCode.所选日期大于维护日期);
            }
        }

        List<Date> holidy = new ArrayList<>();
        List<Date> work = new ArrayList<>();
        for (DateBean bean : holidayList) {
            if (bean.getType() == 10) {
                holidy.add(bean.getDate());
            } else {
                work.add(bean.getDate());
            }

        }
        List<List<Date>> dateList = DateUtil.splitWorkAndSleepDay(startDate,endDate);
        //日期处理
        if (dateList.size() > 0) {
            if (strategyType.equals(StrategyType.holiday.key())) {
                //从工作日中获取节假日，从周末中去掉补班的
                //取交集
                resDateList = dateList.get(0).stream().filter(date ->
                        holidy.contains(date)).collect(toList());
                //dateList.get(1)-  work
                resDateList.addAll(listrem(dateList.get(1),work));
            } else if (strategyType.equals(StrategyType.workday.key())) {
                //从工作日中去除节假日，从周末中去取出补班的
                resDateList = listrem(dateList.get(0),holidy);
                resDateList.addAll(dateList.get(1).stream().filter(date ->
                        work.contains(date)).collect(toList()));
            } else {
                //取交集
                resDateList = dateList.get(0);
                //dateList.get(1)-  work
                resDateList.addAll(dateList.get(1));
            }
        }
        return resDateList;
    }


    /**
     * 操作日志
     */
    @Override
    public Object log(CreateLineStrategyBo param) throws DzcxException {
        OpLog record = new OpLog();
        record.setMoudle(MoudleEnum.商品.key());
        record.setAction(LogActionEnum.线路策略创建.key());
        record.setTargetId(param.getTargetId());
        record.setContent("参数: " + JsonUtil.toJson(param));
        record.setReason(param.getExceptionReason());

        record.setCreatorId(param.getConcurrentUserId());
        record.setCreator(param.getConcurrentUserName());
        record.setCreateTime(new Date());
        log(record);
        return null;
    }


}
